import OSS from 'ali-oss'
import Api from '@/api/tool'
import utils from 'zjy-ui/lib/utils'

export default class OSSUpload {
  client = null // 客户端对象
  region = 'oss-cn-shenzhen'
  bucket = 'bigdatata'
  localStorkey = 'stsTmp' // 存储临时凭证
  ossSts = {} // sts临时凭证数据
  constructor(config) {
    if (config) {
      if (config?.region) this.region = config.region
      if (config?.bucket) this.bucket = config.bucket
      if (config?.localStorkey) this.localStorkey = config.localStorkey
    }
    this.init()
  }
  /**
    * 初始化
    */
  async init(initClient = true) {
    const localStor = utils.storage.localStorage
    let stsTmp = localStor.getItem(this.localStorkey)
    if (!stsTmp) {
      stsTmp = await Api.getStsToken()
      // 获取刷新临时访问凭证的时间间隔
      const cur = new Date(stsTmp.serverTime.replace('-', '/')).getTime()
      const exp = new Date(stsTmp.expiration.replace('-', '/')).getTime() - 2000
      stsTmp.refreshSTSTokenInterval = exp - cur
      // 保存
      localStor.setItem(this.localStorkey, stsTmp, stsTmp.refreshSTSTokenInterval)
    }
    this.ossSts = stsTmp
    if (initClient) this.client = this.getClient(this.ossSts)
  }

  /**
  * 获取客户端
  * @param {object} ossSts sts参数
  * @return {Object}       oss客户端对象
  */
  getClient(ossSts) {
    return new OSS({
      // yourRegion填写Bucket所在地域。以华东1（杭州）为例，Region填写为oss-cn-hangzhou。
      region: this.region,
      // 从STS服务获取的临时访问密钥（AccessKey ID和AccessKey Secret）。
      accessKeyId: ossSts.accessKeyId,
      accessKeySecret: ossSts.accessKeySecret,
      // 从STS服务获取的安全令牌（SecurityToken）。
      stsToken: ossSts.securityToken,
      // 填写Bucket名称，例如examplebucket。
      bucket: this.bucket,

      refreshSTSToken: async () => {
        // 向您搭建的STS服务获取临时访问凭证。
        const ossSts = await this.init(false)
        return {
          accessKeyId: ossSts.accessKeyId,
          accessKeySecret: ossSts.accessKeySecret,
          stsToken: ossSts.securityToken
        }
      },
      // 刷新临时访问凭证的时间间隔，单位为毫秒。
      refreshSTSTokenInterval: ossSts.refreshSTSTokenInterval || 60 * 60 * 1000
    })
  }

  /**
   * 分片上传 和 恢复上传
   * @param {Object}   file        文件对象
   * @param {function} progressFun 过程函数
   */
  upload(file, progressFun) {
    return new Promise((resolve, reject) => {
      utils.dataExistCallFun(() => this.client, async () => {
        try {
          // 填写Object完整路径。Object完整路径中不能包含Bucket名称。
          // 您可以通过自定义文件名（例如exampleobject.txt）或目录（例如exampledir/exampleobject.txt）的形式，实现将文件上传到当前Bucket或Bucket中的指定目录。
          const o = {
            progress: (p, checkpoint) => {
              console.log("====>" + p)
              // checkpoint参数用于记录上传进度，断点续传上传时将记录的checkpoint参数传入即可。浏览器重启后无法直接继续上传，您需要手动触发上传操作。
              this.tempCheckpoint = checkpoint
              if (progressFun) progressFun(p, checkpoint)
            },
            parallel: 4,
            // 设置分片大小。默认值为1 MB，最小值为100 KB。
            partSize: 1024 * 1024 * 5,
            // meta: { year: 2020, people: 'test' },
            mime: 'text/plain'
          }
          // 如果之前传过，则接上次的传输
          if (this.tempCheckpoint) o.tempCheckpoint = this.tempCheckpoint

          const result = await this.client.multipartUpload(this.ossSts.userDir + file.name, file, o)
          resolve(result)
        } catch (e) {
          reject(e)
        }
      })
    })
  }

  /**
    * 暂停
    */
  pause() {
    // 暂停分片上传。
    this.client.cancel()
  }

  /**
    * 销毁
    */
  destory() {
    utils.storage.localStorage.removeItem(this.localStorOnlykey)
  }

  /**
    * 下载
    * @param {string} filename 文件名称
    */
  static async downloadFile(filename) {
    const filePath = await Api.download({ objectName: filename })

    var elink = document.createElement('a')
    elink.download = filename.slice(filename.lastIndexOf('/') + 1)
    elink.style.display = 'none'
    elink.href = filePath
    document.body.appendChild(elink)
    elink.click()
    document.body.removeChild(elink)
  }
}

